#include "PDD.h"

t_pdd *pPdd;
char* PATH;
t_list *listaPeticionesPendientes;
t_list *listaPeticionesResueltas;
int8_t DISCO;
uint16_t remote;

int  main(int argc, char **argv) {

	pthread_t tid_conexion_consola;
	pthread_attr_t attr_conexion_consola;
	
	pPdd = (t_pdd*)malloc(sizeof(t_pdd));

	if(!cargarLogYArchivoConfiguracion(pPdd)){
		printf("ERROR AL CARGAR EL CONFIG");
		return 1;
	}

	t_config *config = getConfig();

	printf("hola mundo");

	PATH = (char*)malloc(strlen(argv)+1);
	strcpy(PATH, argv); // pasamos el path del archivo cuando iniciamos el proceso
	DISCO = abrirArchivo();


	/*inicializo listas*/
	listaPeticionesPendientes = collection_list_create();
	listaPeticionesResueltas = collection_list_create();

	if (config->algoritmoPlanificacion == FSCAN){

		t_listaAtencion *atencion = (t_listaAtencion*)malloc(sizeof(t_listaAtencion));
		atencion->antencion = 1;
		t_list *lista1 = collection_list_create();
		atencion->pendientes = lista1;
		collection_list_add(listaPeticionesPendientes, atencion);

		t_listaAtencion *atencion2 = (t_listaAtencion*)malloc(sizeof(t_listaAtencion));
		atencion2->antencion = 0;
		t_list *lista2 = collection_list_create();
		atencion2->pendientes = lista2;
		collection_list_add(listaPeticionesPendientes, atencion2);
	}
	else
	{
		t_listaAtencion *atencion = (t_listaAtencion*)malloc(sizeof(t_listaAtencion));
		atencion->antencion = 1;
		atencion->sentido = ASCENDENTE;
		t_list *lista1 = collection_list_create();
		atencion->pendientes = lista1;
		collection_list_add(listaPeticionesPendientes, atencion);

		t_listaAtencion *atencion2 = (t_listaAtencion*)malloc(sizeof(t_listaAtencion));
		atencion2->antencion = 0;
		atencion2->sentido = DESCENDENTE;
		t_list *lista2 = collection_list_create();
		atencion2->pendientes = lista2;
		collection_list_add(listaPeticionesPendientes, atencion2);
	}
	
	pthread_attr_init(&attr_conexion_consola);
	if (pthread_create(&tid_conexion_consola, NULL,(void*)conexion_consola, NULL) < 0){
		logMessage(LOG_ERR,"Error pthread_create(&tid_conexion_consola, NULL,(void*)conexion_consola");
	}
	//TODO Apartir de aca se debe empezar a realizar los siguientes metodos

	/* -> Inicializar protocolos de comunicacion*/
	pthread_t tidComunic;
	if (pthread_create(&tidComunic, NULL,(void*)inicializarComunicacion, NULL) < 0){
		logMessage(LOG_ERR,"Error (pthread_create(&tidComunic, NULL,(void*)inicializarComunicacion, NULL)");
	}

	/*pthread_t procesoPPD;
	if (pthread_create(&procesoPPD, NULL,(void*)inicializarPorcesoPPD, (void*)DISCO) < 0){
		logMessage(LOG_ERR,"Error (pthread_create(&procesoPPD, NULL,(void*)inicializarPorcesoPPD, (void*)DISCO)");
	}*/

	pthread_t procesoEnvioRes;
	if (pthread_create(&procesoEnvioRes, NULL,(void*)generarSocketEnvioRAID, NULL) < 0){
		logMessage(LOG_ERR,"Error (pthread_create(&procesoEnvioRes, NULL,(void*)generarSocketEnvioRAID, NULL) < 0)");
	}
	//pthread_join(tid_conexion_consola,NULL);
	while(1);
	return 0;
}

t_socket_client *getSocketDispositivo(){
	return NULL;
}

void setSocketDispositivo(t_socket_client *client){

}

void * conexion_consola(){
	pid_t child_pid;
	uint16_t local,n=0;
	char mensaje[100];
	
	/* -> Inicializar consola(queda en escucha de una conexion)*/
	local = Abre_Socket_Unix(SOCK_PATH);

	printf("Connecting.....\n");

	child_pid = fork();
	if (child_pid == 0){
		/*Le paso como parametros el path donde se encuentra el .o que ejecuta la consola*/
		execv ("/home/utn_so/Desarrollo/Workspace/Fuselage_PDD/Debug/consolaPDD",NULL);
	}

	remote = Acepta_Conexion_Cliente(local);

	printf("Connected!\n");

	while (n >= 0) {
		memset(&mensaje[0], '\0', sizeof(char) * strlen(mensaje));
		n = recv(remote, mensaje, 100, 0);
		if (mensaje[0] == 'F'){
			break;
		}if (n < 0){
				perror("Error recv in conexion_consola from PDD");
		}

		interpretar_msj(remote, mensaje);

	}
	close(remote);
	return(0);

}
	

void setCHSActual(t_chs* chs){
	pPdd->chsActual = chs;
}

t_chs * getCHSActual(){
	return pPdd->chsActual;
}

t_config* getConfig(){
	return pPdd->configArch;
}

void setConfig(t_config *config){
	pPdd->configArch = config;
}

t_peticion *inicializaPeticion(int nSector){

	t_peticion *pet = (t_peticion*)malloc(sizeof(t_peticion));
	pet->nSector = nSector;
	pet->length = 0;
	pet->tOperacion = LECTURA;

	return pet;
}

t_list *getListPeticiones(int algoritmo){
	t_list *lista;

	if (algoritmo == FSCAN){
		lista = listaAtencion()->pendientes;
	}

	if (algoritmo == CSCAN){
		t_listaAtencion *aten = listaAscendente();
		if (aten->antencion == 1)
			lista = aten->pendientes;
		else{
			lista = listaDescendente()->pendientes;
		}
	}

	return lista;
}

t_list *getListCargaPeticiones(int algoritmo, int sentido)
{
	t_list *lista;

	if (algoritmo == FSCAN){
		lista = listaAEscucha()->pendientes;
	}

	if (algoritmo == CSCAN){
		if (sentido == ASCENDENTE)
			lista = listaAscendente()->pendientes;
		else
			lista = listaDescendente()->pendientes;
	}
	return lista;
}

void setListPeticiones(){

}

t_list *getListPeticionesResueltas(){
	return listaPeticionesResueltas;
}

void setListPeticionesResueltas(t_list *lista){
	listaPeticionesResueltas = lista;
}

t_listaAtencion *listaAEscucha(){
	return (t_listaAtencion*)collection_list_find(listaPeticionesPendientes,listaEnEscucha);
}

t_listaAtencion *listaAtencion(){
	return (t_listaAtencion*)collection_list_find(listaPeticionesPendientes, listaAtencion);
}

void *listaEnEscucha(t_listaAtencion *elem){
	return elem->antencion == 0;
}

void *listaEnAtencion(t_listaAtencion *elem){
	return elem->antencion == 1;
}

t_listaAtencion *listaAscendente(){
	return (t_listaAtencion*)collection_list_find(listaPeticionesPendientes,listaEnAscenso);
}

t_listaAtencion *listaDescendente(){
	return (t_listaAtencion*)collection_list_find(listaPeticionesPendientes, listaEnDescenso);
}

void *listaEnAscenso(t_listaAtencion *elem){
	return elem->sentido = ASCENDENTE;
}

void *listaEnDescenso(t_listaAtencion *elem){
	return elem->sentido = DESCENDENTE;
}

char* getDescripcionDeError(uint32_t error){
	char *desc = (char*)malloc(sizeof(100));
	/*Hay que hacer un switch con los distintos errore sposibles*/
	memcpy(desc, "error por algun motivo", sizeof("error por algun motivo")+1);

	return desc;
}

t_peticionResuelta *getPeticionResueltaByClient(t_socket_client *client){

	t_list *list = getListPeticionesResueltas();
	int cantPet = 0;

	while (collection_list_size(list) > cantPet){

		t_peticionResuelta *petResuelta = (t_peticionResuelta*)collection_list_get(list,cantPet);
		if (sockets_equalsClients(petResuelta->client,client)){
			return (t_peticionResuelta*)collection_list_remove(list, cantPet);
		}
	}
	return NULL;
}

void destroyPeticion(t_peticion *peticion){
	free(peticion->info);
	free(peticion);
}
